跳到主要内容

Maven 父工程的使用与聚合

dependency 的 type为 pom

dependency 中 type 默认为 jar 即引入一个特定的 jar 包。那么为什么还会有 type 为 pom 呢?

当我们需要引入很多 jar 包的时候会导致 pom.xml 过大,我们可以想到的一种解决方案是定义一个父项目,但是父项目只有一个,也有可能导致父项目的 pom.xml 文件过大。

这个时候我们引进来一个 type 为 pom,意味着我们可以将所有的 jar 包打包成一个 pom,然后我们依赖了 pom,即可以下载下来所有依赖的 jar 包

<!-- <type>pom</type> 把 spring-boot-dependencies 引入为 pom 文件 -->
<!-- <scope>import</scope>解决单继承问题,类似parent标签,把spring-boot-dependencies引入到dependencyManagement -->

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

子pom 使用父pom 依赖,情况一:子 pom 引用父 pom 声明的依赖。

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

dependencyManagement 里配置并不会实际引入,只是为了版本管理,实际引入需要直接在 dependencies 中添加。

因为父pom 已经设置版本,子pom 不需要写版本号,会追溯到父pom 的版本。

Maven 依赖的传递

参考资料 Maven依赖的查询、传递和继承

依赖会被传递: A依赖C,B依赖A ==> B依赖C(这种依赖是基于 compile 这个范围进行传递)

聚合和继承

如何我们的项目包含多个模块我们一个一个编译,会太麻烦,我们可以建一个聚合项目,通过 modules 来统一操作

继承可以复用父类的 pom,可以为我们提高 pom 复用,子模块可以通过 parent 标签来导入要继承的 pom

依赖继承采用 dependencyManagement 用来统一管理,在子模块中需要那个依赖,只需要写 groupId 和 artifactId 就可以,采用依赖管理既可以有效的控制依赖,有能在一定程度上避免依赖冲突。

dependencyManagement 应用场景

dependencyManagement 用于统一管理各个子模块的版本号,通常只会在组织或项目的最顶层的父 pom 看到 dependencyManagement

为了项目的正确运行,必须让所有的子模块使用依赖项的统一版本,必须确保应用的各个项目的依赖项和版本一致,才能保证测试的和发布的是相同的结果。

在我们项目顶层的 pom 文件中,我们会看到 dependencyManagement 元素。通过它元素来管理 jar 包的版本,让子项目中引用一个依赖而不用显示的列出版本号。Maven 会沿着父子层次向上走,直到找到一个拥有 dependencyManagement 元素的项目,然后它就会使用在这个 dependencyManagement 元素中指定的版本号。

父 pom 中 dependencyManagement 如下:

<modules>
<module>module1</module>
</modules>

<properties>
<spring-version>3.1.1.RELEASE</spring-version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
</dependencyManagement>

子模块 module1 中 dependency 声明如下所示:

<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
</dependencies>

这样做的好处:统一管理项目的版本号,确保应用的各个项目的依赖和版本一致,才能保证测试的和发布的是相同的成果,因此,在顶层 pom 中定义共同的依赖关系。

同时可以避免在每个使用的子项目中都声明一个版本号,这样想升级或者切换到另一个版本时,只需要在父类容器里更新,不需要任何一个子项目的修改;如果某个子项目需要另外一个版本号时,只需要在 dependencies 中声明一个版本号即可。子类就会使用子类声明的版本号,不继承于父类版本号。

父类 dependencies 的作用

dependencyManagement 里只是声明依赖,并不实现引入,因此子项目需要显式的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且 version 和 scope 都读取自父 pom;

另外如果子项目中指定了版本号,那么会使用子项目中指定的 jar版本。

dependencies 即使在子模块中不写该依赖项,那么子模块仍然会从父项目中继承该依赖项(全部继承)。

在实际的项目开发中,推荐在父 pom 中使用 dependencyManagement 对项目中使用到的依赖包进行统一的管理。

多模块命名上的问题

在使用 IDEA 时,会经常发现修改同一个包下的文件会导致其它的同名包的文件也被修改,这个可能是 IDEA 的 BUG

如上图的这种,两个子模块里面的包名路径相似,如果这时对其中一个模块的包名改名会出现下面这种提示:

解决办法就是在这种子模块包名再创建一个子包,再在子包里面拖动类,不要拖动包,在新建的包里一个个创建同名包(或者直接复制),避免冲突,然后再把文件拖过去,这样修改就不会再影响到其它的包了